// Minimal Unicode Property

// General_Category Ex-Other Ex-Line_Separator Ex-Paragraph_Separator
// http://www.unicode.org/reports/tr44/#General_Category_Values
import Control      from './Control'
import Format       from './Format'
import Private_Use  from './Private_Use'
import Surrogate    from './Surrogate'
import Unassigned   from './Unassigned'

import Lowercase_Letter from './Lowercase_Letter'
import Modifier_Letter  from './Modifier_Letter'
import Other_Letter     from './Other_Letter'
import Titlecase_Letter from './Titlecase_Letter'
import Uppercase_Letter from './Uppercase_Letter'

import Enclosing_Mark   from './Enclosing_Mark'
import Nonspacing_Mark  from './Nonspacing_Mark'
import Spacing_Mark     from './Spacing_Mark'

import Decimal_Number from './Decimal_Number'
import Letter_Number  from './Letter_Number'
import Other_Number   from './Other_Number'

import Close_Punctuation      from './Close_Punctuation'
import Connector_Punctuation  from './Connector_Punctuation'
import Dash_Punctuation       from './Dash_Punctuation'
import Final_Punctuation      from './Final_Punctuation'
import Initial_Punctuation    from './Initial_Punctuation'
import Open_Punctuation       from './Open_Punctuation'
import Other_Punctuation      from './Other_Punctuation'

import Currency_Symbol  from './Currency_Symbol'
import Math_Symbol      from './Math_Symbol'
import Modifier_Symbol  from './Modifier_Symbol'
import Other_Symbol     from './Other_Symbol'

import Space_Separator  from './Space_Separator'

// https://www.unicode.org/reports/tr51/
// import Emoji              from  './Emoji'
// import EastAsianWide      from  './EastAsianWide'
// import EastAsianAmbiguous from  './EastAsianAmbiguous'

// https://unicode.org/Public/11.0.0/ucd/PropList.txt
//
// ASCII_Hex_Digit
// Bidi_Control
// Dash
// Diacritic
// Extender
// Hex_Digit
// Hyphen
// Ideographic
// IDS_Binary_Operator
// IDS_Trinary_Operator
// Join_Control
// Logical_Order_Exception
// Noncharacter_Code_Point
// Other_Alphabetic
// Other_Default_Ignorable_Code_Point
// Other_Grapheme_Extend
// Other_ID_Continue
// Other_ID_Start
// Other_Lowercase
// Other_Math
// Other_Uppercase
// Pattern_Syntax
// Pattern_White_Space
// Prepended_Concatenation_Mark
// Quotation_Mark
// Radical
// Regional_Indicator // U+1F1E6..U+1F1FF
// Sentence_Terminal
// Soft_Dotted
// Terminal_Punctuation
// Unified_Ideograph
// Variation_Selector
// White_Space

const

  // KindMask    = 0x1F,
  // FlagMask    = 0xE0,

  // hiAmbiguous   = 0x08,
  // hiWide        = 0x10,
  // hiEmoji       = 0x20,

  // !!KEEP ORDER
  // https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt
  Cn            = 0x00,  // Unassigned, Must be 0
  Cf            = 0x01,  // Format
  Co            = 0x02,  // Private_Use
  Cs            = 0x03,  // Surrogate
  Cc            = 0x04,  // Control
  Zl            = 0x05,  // Line_Separator
  Zp            = 0x06,  // Paragraph_Separator
  Zs            = 0x07,  // Space_Separator
  Ll            = 0x08,  // Lowercase_Letter
  Lm            = 0x09,  // Modifier_Letter
  Lo            = 0x0A,  // Other_Letter
  Lt            = 0x0B,  // Titlecase_Letter
  Lu            = 0x0C,  // Uppercase_Letter
  Mc            = 0x0D,  // Spacing_Mark
  Me            = 0x0E,  // Enclosing_Mark
  Mn            = 0x0F,  // Nonspacing_Mark
  Nd            = 0x10,  // Decimal_Number
  Nl            = 0x11,  // Letter_Number
  No            = 0x12,  // Other_Number
  Pc            = 0x13,  // Connector_Punctuation
  Pd            = 0x14,  // Dash_Punctuation
  Pe            = 0x15,  // Close_Punctuation
  Pf            = 0x16,  // Final_Punctuation
  Pi            = 0x17,  // Initial_Punctuation
  Po            = 0x18,  // Other_Punctuation
  Ps            = 0x19,  // Open_Punctuation
  Sc            = 0x1A,  // Currency_Symbol
  Sk            = 0x1B,  // Modifier_Symbol
  Sm            = 0x1C,  // Math_Symbol
  So            = 0x1D,  // Other_Symbol

  codepoints      = new Uint8Array(0x10FFFF + 1)

let longnames = [
  'Unassigned',
  'Format',
  'Private_Use',
  'Surrogate',
  'Control',
  'Line_Separator',
  'Paragraph_Separator',
  'Space_Separator',
  'Lowercase_Letter',
  'Modifier_Letter',
  'Other_Letter',
  'Titlecase_Letter',
  'Uppercase_Letter',
  'Spacing_Mark',
  'Enclosing_Mark',
  'Nonspacing_Mark',
  'Decimal_Number',
  'Letter_Number',
  'Other_Number',
  'Connector_Punctuation',
  'Dash_Punctuation',
  'Close_Punctuation',
  'Final_Punctuation',
  'Initial_Punctuation',
  'Other_Punctuation',
  'Open_Punctuation',
  'Currency_Symbol',
  'Modifier_Symbol',
  'Math_Symbol',
  'Other_Symbol',
]

Control(property(Cc))
Format(property(Cf))
Private_Use(property(Co))
Surrogate(property(Cs))
Lowercase_Letter(property(Ll))
Uppercase_Letter(property(Lu))
Modifier_Letter(property(Lm))
Other_Letter(property(Lo))
Titlecase_Letter(property(Lt))
Spacing_Mark(property(Mc))
Enclosing_Mark(property(Me))
Nonspacing_Mark(property(Mn))
Decimal_Number(property(Nd))
Letter_Number(property(Nl))
Other_Number(property(No))
Connector_Punctuation(property(Pc))
Dash_Punctuation(property(Pd))
Other_Punctuation(property(Po))
Initial_Punctuation(property(Pi))
Final_Punctuation(property(Pf))
Open_Punctuation(property(Ps))
Close_Punctuation(property(Pe))
Currency_Symbol(property(Sc))
Modifier_Symbol(property(Sk))
Math_Symbol(property(Sm))
Other_Symbol(property(So))
codepoints[0x2028] = Zl
codepoints[0x2029] = Zp
Space_Separator(property(Zs))

// EastAsianAmbiguous(setFlag(hiAmbiguous))

// EastAsianWide(setFlag(hiWide))

// Emoji(setFlag(hiEmoji))

Unassigned(function (...cp) {
  cp.forEach(cp => clean(cp))
  return {
    r: function (cp, last) {
      while (cp <= last) clean(cp++)
      return this
    }
  }
})

// https://www.unicode.org/reports/tr31/#Introduction
// https://www.unicode.org/reports/tr44/#PropList.txt
//
// Derived Property: ID_Start
//  Characters that can start an identifier.
//  Generated from:
//      Lu + Ll + Lt + Lm + Lo + Nl
//    + Other_ID_Start
//    - Pattern_Syntax
//    - Pattern_White_Space
//
// Derived Property: ID_Continue
//  Characters that can start an identifier.
//  Generated from:
//      ID_Start
//    + Mc
//    + Mn
//    + Nd
//    + Pc
//    + Other_ID_Continue
//    - Pattern_Syntax
//    - Pattern_White_Space
//
// Just exclude 2E2F ; Pattern_Syntax # Lm VERTICAL TILDE
const
  Other_ID_Start = [0x1885, 0x1886, 0x2118, 0x212E, 0x309B, 0x309C],
  // Mn, Sm, So, Sk
  Other_ID_Continue = [
    0x00B7, 0x0387, // Po
    0x1369, 0x136A, 0x136B, 0x136C, 0x136D, 0x136E, 0x136F, 0x1370, 0x1371,
    // No
    0x19DA
    // No
  ]

// function setFlag (cc) {
//   return function (...cp) {
//     cp.forEach(cp => codepoints[cp] |= cc)
//     return {
//       r: function (cp, last) {
//         while (cp <= last) codepoints[cp++] |= cc
//         return this
//       }
//     }
//   }
// }

function clean (cp) {
  codepoints[cp] = 0
  // let fc = codepoints[cp]
  // if (fc === hiAmbiguous || fc === hiWide)
  //   codepoints[cp] = 0
  // else if (fc) {
  //   throw `oops ${cp.toString(16)} ${fc.toString(16)}`
  // }
}

function property (cc) {
  return function (...cp) {
    cp.forEach(cp => codepoints[cp] = cc)
    return {
      r: function (first, last) {
        codepoints.fill(cc, first, last + 1)
        return this
      }
    }
  }
}

function gcValue (cp) { // General Category Value
  return codepoints[cp]
}

function gcName (gc) { // Unicode General Category
  return longnames[gc]
}


export {
  Cn,
  Cf,
  Co,
  Cs,
  Cc,
  Zl,
  Zp,
  Zs,
  Ll,
  Lm,
  Lo,
  Lt,
  Lu,
  Mc,
  Me,
  Mn,
  Nd,
  Nl,
  No,
  Pc,
  Pd,
  Pe,
  Pf,
  Pi,
  Po,
  Ps,
  Sc,
  Sk,
  Sm,
  So,

  gcValue,
  gcName,

  Other_ID_Start,
  Other_ID_Continue

  // hiAmbiguous,
  // hiWide,
  // hiEmoji
}
